import { any, must } from "../core/logic";
import { Engine } from "../Engine";
import { Geometry } from "./Geometry";
import { atlasJsonLoader } from "../assets/loader/AtlasJsonLoader";
import { process } from "../process/worker/process";
/**
 * 材质类。
 * @class
 * @memberof w
 */
class TextGeometry extends Geometry {
 /**
     * 文字几何体的构造方法。
     * @constructor
     * @param {*} opts 
     * @param {boolean} opts.back 【选填】对文字的解析是否放在后台，缺省：true，在后台进行解析。
     * @param {object} opts.data 【必填】文字数据,多个点可用数组。
     * @param {array} opts.data.text 文字内容数据。
     * @param {array[]} opts.data.position 文字位置数据。
     * @param {array } opts.color 【选填】文字颜色值。
     * @param {string } opts.fontUrl 【必填】文字字体atlas.json文件所在路径。
     * @param {array } opts.fontSize 【选填】文字字体大小，缺省值：[12,12]。
     * @param {number } opts.width 【选填】文字容器像素宽度，缺省值：300。
     * @param {number|string } opts.height 【选填】文字容器像素高度，自适应高度时使用'auto', 缺省值：auto 。
     * @param {number } opts.lineHeight 【选填】文字行高，缺省值：30。
     * @param {number } opts.space 【选填】文字字符间距，缺省值：2。
     * @param {string } opts.overflow 【选填】文字溢出样式，可选值：ellipsis(省略号)，hidden(隐藏)，缺省值：ellipsis。
     * @param {string} opts.horizontalLocation 【选填】文字相对于位置中心的水平位置，可选值：left,center,right。缺省值：center。
     * @param {string} opts.verticalLocation 【选填】文字相对于位置中心的垂直位置，可选值：top,middle,bottom。缺省值：middle。
     * @param {string} opts.textAlign 【选填】文字在容器内水平居中方式，可选值：left,center,right。缺省值：center。
     * @param {string} opts.verticalAlign 【选填】文字在容器内垂直居中方式，可选值：top,middle,bottom。缺省值：middle。
     * @param {array} opts.relativeShift 【选填】文字相对于位置中心的偏移。缺省值：[0,0]。
     * @param {function} opts.callback 【选填】文字数据生成完成回调。
     */
  constructor(opts = {}, share) {
    super({autoUpdate: false});
    this.type="PointGeometry";
    this.geometryType = "PointGeometry";
    this._hash = "";
    this.rawColor = any(opts.color, new Float32Array([]));
    this.varySize = any(opts.varySize, false);
    this.promise = [];
    let camera=Engine.instance.scene.getCamera();
    let cameraDistance = camera.trans.position.distanceTo(camera.at)
    this.pixelRatio = cameraDistance*2.309401076758503/camera.size[1];
    this.fontUrl = must(opts.fontUrl);
    this.fontSize = any(opts.fontSize, [12,12]);
    this.width = any(opts.width, 300);
    this.height = any(opts.height, 'auto');
    this.lineHeight = any(opts.lineHeight, 30)
    this.horizontalLocation = any(opts.horizontalLocation, 'center');
    this.verticalLocation = any(opts.verticalLocation, 'middle');
    this.textAlign = any(opts.textAlign, 'center');
    this.verticalAlign = any(opts.verticalAlign, 'middle');
    this.space = any(opts.space, 2);
    this.overflow = any(opts.overflow, 'ellipsis');
    this.relativeShift =  any(opts.relativeShift, [0,0]);
    this.shape = any(opts.shape, 'rect');
    this.calcData = opts.calcData;
    this.processCallback = any(opts.callback , () => {})
    this.data=any(opts.data,[]);
    
  }
  set data(v){
    this._data=v;
    this.noRepeatPoints = v.position;
    if(this.fontInfo) {
        this.fillPosition();
    } else {
        Promise.all(this.promise).then(() => {
            this.fillPosition();
        })
    }
    return this;
  }
  get data(){
      return this._data;
  }
  set varySize(v){
    this._varySize = v;
    this.addConfigParam("pointSizeVarying", v);
    return this;
  }
  get varySize(){
      return this._varySize;
  }
  set fontUrl(v) {
    this._fontUrl = v;
    const loader = atlasJsonLoader.load(v).then((atlas) => {
        let fontInfo = atlas ? atlas.info : undefined;
        if (atlas) {
            fontInfo = atlas.info;
        }
        this.fontInfo = fontInfo;
        
    })
    this.promise.push(loader);
    return this;
  }
  /**
   * @property {String} text  url 文字图集(路径)。/atlas.json atlas.png。
   */
  get fontUrl() {
      return this._fontUrl;
  }
  set fontInfo(v) {
      this._fontInfo = v;
      return this;
  }
  /**
   * @property {String} text  url 文字图集(路径)。/atlas.json atlas.png。
   */
  get fontInfo() {
      return this._fontInfo;
  }
  set fontSize(v){
    this._fontSize=v;
    this.addParam("pointSize");
    return this;
  }
  get fontSize(){
      return this._fontSize;
  }
  set width(v){
      this._width=v;
      return this;
  }
  get width(){
      return this._width;
  }
  set height(v){
      this._height=v;
      return this;
  }
  get height(){
      return this._height;
  }
  set lineHeight(v){
      this._lineHeight=v;
      return this;
  }
  get lineHeight(){
      return this._lineHeight;
  }
  set textAlign(v){
      this._textAlign=v;
      return this;
  }
  get textAlign(){
      return this._textAlign;
  }
  set verticalAlign(v){
      this._verticalAlign=v;
      return this;
  }
  get verticalAlign(){
      return this._verticalAlign;
  }
  set space(v){
      this._space=v;
      return this;
  }
  get space(){
      return this._space;
  }
  set overflow(v){
      this._overflow=v;
      return this;
  }
  get overflow(){
      return this._overflow;
  }

  set horizontalLocation(v){
      this._horizontalLocation=v;
      return this;
  }
  get horizontalLocation(){
      return this._horizontalLocation;
  }
  set verticalLocation(v){
      this._verticalLocation=v;
      return this;
  }
  get verticalLocation(){
      return this._verticalLocation;
  }
  set pointNormal(v){
      this._pointNormal=v;
      this.addParam("pointNormal");
      return this;
  }
  get pointNormal(){
      return this._pointNormal;
  }
  set offset(v){
    this._offset=v;
    this.addParam("offset");
    return this;
  }
  get offset(){
      return this._offset;
  }
  set relativeShift(v){
      this._relativeShift = v;
      this.addParam("relativeShift");
      return this;
  }
  get relativeShift(){
      return this._relativeShift;
  }
  
  
  getPoints() {
    let noRepeatPoints = [];
    for (var j = 0; j < this.rawPosition.length; j += 3) {
        if(!(noRepeatPoints[noRepeatPoints.length - 1] && this.comparePoint(noRepeatPoints[noRepeatPoints.length - 1] ,[this.rawPosition[j], this.rawPosition[j+1], this.rawPosition[j+2]]))) {
            noRepeatPoints.push([this.rawPosition[j], this.rawPosition[j+1], this.rawPosition[j+2]])
        }
    }
    return noRepeatPoints;
}
fillPosition(){
  if(this.calcData) {
      let  {
          positions,
          offsets,
          indices_array,
          directions,
          uvs,
          colors,
      } = this.calcData;
      this.indices = indices_array;
      this.position = positions;
      this.offset = offsets;
      this.pointNormal = directions;
      this.texCood0 = uvs;
      if(colors.length) {
          this.color = colors;
      }
      this.autoUpdate = true;
      this.update();
      this.processCallback(message.data);
  } else {
      process({
          type:"text",
          back: this.back,
          data: this.data,
          color: this.rawColor, 
          fontInfo: this.fontInfo,
          fontSize: this.fontSize,
          width: this.width,
          height:this.height,
          lineHeight: this.lineHeight,
          horizontalLocation: this.horizontalLocation,
          verticalLocation: this.verticalLocation,
          textAlign: this.textAlign,
          verticalAlign: this.verticalAlign,
          space: this.space,
          overflow: this.overflow,
          varySize: this.varySize,
          pixelRatio: this.pixelRatio,
      },(message)=>{
          let  {
              positions,
              offsets,
              indices_array,
              directions,
              uvs,
              colors,
          } = message.data;
          this.indices = indices_array;
          this.position = positions;
          this.offset = offsets;
          this.pointNormal = directions;
          this.texCood0 = uvs;
          if(colors.length) {
              this.color = colors;
          }
          this.autoUpdate = true;
          this.update();
          this.processCallback(message.data);
      })
  }
  
}

  toGPU() {
    if (this.has("pointSize")) {
      let data = [...this.fontSize];
      if(this.varySize) {
          data = data.map(item => item*this.pixelRatio);
      }
      this.bufferToGPU(new Float32Array(data), 'pointSize', GPUShaderStage.VERTEX);
    }
    if (this.has("pointNormal")) {
      this.initVertex(this.pointNormal, "pointNormal", 3);
    }
    if (this.has("offset")) {
      this.initVertex(this.offset, "offset", 2);
    }
    if (this.has("relativeShift")) {
      let data = [...this.relativeShift];
      if(this.varySize) {
          data = data.map(item => item*this.pixelRatio);
      }
      this.bufferToGPU(new Float32Array(data), 'relativeShift', GPUShaderStage.VERTEX);
    }
    super.toGPU();
  }
    

  
  
}

export { TextGeometry };
